function isObject(value) {
  let valueType = typeof value;
  return value !== null && (valueType == "object" || valueType == "function");
}

// map 使用 弱引用的 WeakMap 加强内存吸收
function deepCopy(originValue, map = new WeakMap()) {
  // Map and Set, 浅拷贝
  if (originValue instanceof Map) return new Map([...originValue]);
  if (originValue instanceof Set) return new Set([...originValue]);

  // 判断是不是symbol
  if (typeof originValue == "symbol") return Symbol(originValue.description);

  // 判断是不是function
  if (typeof originValue == "function") return originValue;

  // 普通的类型直接返回
  if (!isObject(originValue)) return originValue;

  // 处理循环引用
  if (map.has(originValue)) return map.get(originValue);

  // 数组和对象的初始化
  let newObject = Array.isArray(originValue) ? [] : {};

  // map 缓存
  map.set(originValue, newObject);

  // 数组和对象处理
  for (let key in originValue) {
    newObject[key] = deepCopy(originValue[key], map);
  }

  // symbol 特殊处理
  const symbolKeys = Object.getOwnPropertySymbols(originValue);
  for (const sKey of symbolKeys) {
    // 重新创建了一个， 其实是没有必要的
    const newSKey = Symbol(sKey.description);
    newObject[newSKey] = deepCopy(originValue[sKey], map);
  }
  return newObject;
}

let obj = {
  name: "xjh",
  fn: function () {
    console.log("xjh");
  },
  friend: {
    age: 10,
    address: {
      place: "上海",
    },
  },
};

// 只能这样赋值
obj.inner = obj;

let newObj = deepCopy(obj);

console.log(newObj === obj);
obj.friend.address.place = "北京";
console.log(newObj);
console.log(obj.friend.address.place);
console.log(obj.inner.inner);
